/**
 * Contains {@link Network}
 */
package logic;

import java.io.Serializable;
import java.net.Inet4Address;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Iterator;

import logic.connectors.NetworkInterface;
import logic.pathelements.PathElement;
import java.util.Set;
import logic.connectors.Connector;
import logic.pathelements.ActiveElement;

/**
 * Path elements container. Allows communicate with them.
 * @author Alexey Akimov <frinatella@gmail.com>
 */
public class Network implements Serializable, Iterable<PathElement> {
    
    /**
     * ID for serialization
     */
    private static final long serialVersionUID = 5029623292810428643L;
	
    /**
     * this network path elements
     */
    private HashMap<Integer, PathElement> pathElements;

    /**
     * Constructor
     */
    public Network() {
        this.pathElements = new HashMap<Integer, PathElement>();
    }
      
    /**
     * adds path element into network
     * @param pathElement 
     */
    public void addPathElement(PathElement pathElement) {
        pathElements.put(pathElement.getId(), pathElement);
    }
    
    /**
     * Connects first path element connector to other connector other path element
     * @param firstElementId first path element id
     * @param firstElementConnectorNumber first path element connector number
     * @param otherElementId other path element id
     * @param otherElementConnectorNumber other path element connector number
     */
    public void connect(Integer firstElementId, int firstElementConnectorNumber, 
    		Integer otherElementId, int otherElementConnectorNumber) {
        pathElements.get(firstElementId).connect(firstElementConnectorNumber, 
        				pathElements.get(otherElementId), otherElementConnectorNumber);
    }
    
    /**
     * Disconnect path element connector
     * @param elementId path element id
     * @param elementConnectorNumber  path element connector number
     */
    public void disconnect(Integer elementId, int elementConnectorNumber) {
        pathElements.get(elementId).disconnect(elementConnectorNumber);
    }
    
    /**
     * Getter
     * @param id path element id
     * @return path element
     */
    public PathElement getPathElement(Integer id) {
        return pathElements.get(id);
    }
    
    /**
     * Getter
     * @param ip active path element network interface ip
     * @return active path element if find it or null otherwise
     */
    public ActiveElement getPathElementByIp(Inet4Address ip) {
        Set<Integer> keySet = pathElements.keySet();
        PathElement pathElement;
        for(Integer key : keySet) {
            pathElement = pathElements.get(key);
            if (pathElement instanceof ActiveElement) {
                for( Connector connector: pathElement.getConnectors() ) {
                    if (((NetworkInterface) connector).getIp().equals(ip)) {
                        return (ActiveElement) pathElement;
                    }
                }
            }
        }
        return null;
    }
    
    /**
     * Getter
     * @param ip text representation of active path element network interface ip 
     * @return active path element if find it or null otherwise
     * @throws UnknownHostException 
     */
    public ActiveElement getPathElementByIp(String ip) throws UnknownHostException {
        return getPathElementByIp((Inet4Address) Inet4Address.getByName(ip));
    }
    
    /**
     * Removes path element from this network
     * @param id path element id
     */
    public void removePathElement(Integer id) {
        pathElements.remove(id);
    }
    
    /**
     * Setter
     * @param elementId active path element id
     * @param networkInterfaceNumber  path element network interfface number
     * @param ip active path element network interface ip
     */
    public void setActivePathElmentNetworkInterfaceIp(Integer elementId, int networkInterfaceNumber, Inet4Address ip) {
        ((ActiveElement) pathElements.get(elementId)).setIp(networkInterfaceNumber, ip);
    }
    
    /**
     * Setter
     * @param elementId active path element id
     * @param networkInterfaceNumber  path element network interfface number
     * @param ip active path element network interface ip text representation
     */
    public void setActivePathElmentNetworkInterfaceIp(Integer elementId, int networkInterfaceNumber, String ip) throws UnknownHostException {
        ((ActiveElement) pathElements.get(elementId)).setIp(networkInterfaceNumber, ip);
    }

    @Override
    public Iterator<PathElement> iterator() {
            return pathElements.values().iterator();
    }
    
    @Override
    public String toString() {
        String result = "";
        for (PathElement pathElement : pathElements.values()) {
            result += pathElement.toString();
        }
        return result;
    }


    
}
